function init() {
}

/**
 * This implementation will create two separate arrays. One for the pitches and one for the length.
 */
function run1() {
    var pitches = [];
    var tickLens = [];
    var writer = function(voice, pitch, tickLen) {
        var tlSum = tickLen / 10;
        while(true) {
            var tl = tlSum > 255 ? 255 : tlSum;
            if(pitches[voice] == undefined) {
                pitches[voice] = "" + pitch;
            }
            else {
                pitches[voice] += "," + pitch;
            }

            if(tickLens[voice] == undefined) {
                tickLens[voice] = "" + tl;
            }
            else {
                tickLens[voice] += "," + tl;
            }
            if(tlSum > 255) {
                tlSum -= 255;
            }
            else {
                break;
            }
        }
    };
    exportToOutput(writer);

    var text = "";
    for(var v = 0; v < pitches.length; v++) {
        text += "const uint8_t p" + v + "_notes[] PROGMEM = { " + pitches[v] + " };\n";
        text += "const uint8_t p" + v + "_delays[] PROGMEM = { " + tickLens[v] + " };\n";
        text += "\n";
    }
    messageBox(text);
}

/**
 * This implementation will create one array where the pitch is always followed by the length. The array is closed by a 0,0 pair.
 */
function run2() {
    var music = [];
    var writer = function(voice, pitch, tickLen) {
        var tlSum = tickLen / 10;
        while(true) {
            var tl = tlSum > 255 ? 255 : tlSum;
            if(music[voice] == undefined) {
                music[voice] = "" + pitch;
            }
            else {
                music[voice] += "," + pitch;
            }
            music[voice] += "," + tl;

            if(tlSum > 255) {
                tlSum -= 255;
            }
            else {
                break;
            }
        }
    };
    exportToOutput(writer);

    var text = "";
    for(var v = 0; v < music.length; v++) {
        text += "const uint8_t staff" + v + "[] PROGMEM = { " + music[v] + ",0,0 };\n";
        text += "\n";
    }
    messageBox(text);
}


var mscorePlugin = {
    majorVersion:  1,
    minorVersion:  1,
    menu: 'Plugins.H Export',
    init: init,
    run: run2
//   ,onClose: close
};


/**
 * This method will call the "func" parameter for every chords can be melody.
 * The callback will be called with the following parameters: (staff, pitch, tickLen) where:
 *  staff - Each staff will be scanned one after an other.
 *  pitch - The pitch of the first note in the chord, or zero for rest.
 *  tickLen - Is the length of the chord (or rest).
 * Please consult MuseScore plugin documentation for the possible values of this variables!
 */
function exportToOutput(func) {
    if(typeof curScore === 'undefined')
    {
        return;
    }

    var cursor = new Cursor(curScore);

    cursor.goToSelectionStart();
    var startStaff = cursor.staff;
    cursor.goToSelectionEnd();
    var endStaff = cursor.staff;
    var endTick = cursor.tick(); // -- If no selection, end of score.

    if(cursor.eos()) {
        // -- No selection.
        startStaff = 0; // -- Start with the first staff.
        endStaff = curScore.staves; // -- End with the last staff.
    }

    for(var staff = startStaff; staff < endStaff; ++staff) {
        for(var voice = 0; voice < 4; voice++) {
            cursor.goToSelectionStart(); // -- Note, that this will also sets voice to zero!
            cursor.voice = voice; // -- Voice need to be reset after goToSelectionStart().
            cursor.staff = staff;
            if(cursor.eos())
            {
                // -- If no selection, beginning of score.
                cursor.rewind()
            }

            var prevPitch = 0;
            var prevTickLen = 0;
            while(cursor.tick() < endTick) {
                var pitch;
                var tickLen;
                if(cursor.isChord()) {
                    var chord = cursor.chord();
                    tickLen = chord.tickLen;
                    if(chord.notes > 0) {
                        var note = chord.note(0);
                        pitch = note.pitch;
                    }
                    else {
                        pitch = 0;
                    }
                } else if(cursor.isRest()) {
                    var rest = cursor.rest();
                    pitch = 0;
                    tickLen = rest.tickLen;
                }
                if(cursor.isChord() || cursor.isRest()) {
                    if(pitch == prevPitch) {
                        prevTickLen += tickLen;
                    }
                    else {
                        if(prevTickLen > 0) {
                            func(staff, prevPitch, prevTickLen);
                        }
                        prevPitch = pitch;
                        prevTickLen = tickLen;
                    }
                }

                cursor.next();
            }
            if(prevTickLen > 0) {
                func(staff, prevPitch, prevTickLen);
            }
        }
    }
}

function messageBox(s) {
    var mb = new QMessageBox();
    mb.setWindowTitle("MuseScore: H Export Plugin");
    mb.text = s;
    mb.exec();
}
mscorePlugin;
